#include <iostream>
#include <string.h>
#include "node.h"
//#include "node.cpp"
#include "Customer_Obj.h"
#include <cassert>
//#include "Customer_Obj.cpp"
#include "Deli.h"
using namespace std;

Deli::Deli() {
        // CONSTRUCTOR -- initially an empty list, so the head and tail are NULL
        head = NULL;
        tail = NULL;
}

Deli::~Deli() {
        // DESTRUCTOR -- the memory needs to be deallocated for the list

        node *delPtr;

    for(start(); isElement(); ) { // initialize to the beginning of the list, and loop for each element
                delPtr = current_index;   // mark the current node for deletion
                advance();                // advance to the next node
                delete delPtr;            // deallocate space for the node
        }
}

Deli::Deli(sync *sync_object, control *control_object, sweeps *sweeps_object) {
        sync_obj = sync_object;
        control_obj = control_object;
        sweeps_obj = sweeps_object;
        timeInLine = 0;
        position = 0;
		served = 0;
		numServed = 0;
		timeArrayCounter = 0;
		int averageTime = 0;
		int longestWait = 0;
		
}


void Deli::setTimeInLine(int position) {
        timeInLine = (position+1)*(50);
}

int Deli::getTimeInLine() {
        return timeInLine;
}

bool Deli::isEmpty() {
        return(head == NULL);
}


void Deli::start() { current_index = head; }

bool Deli::isElement() { return (current_index != NULL); }

void Deli::advance() {
        assert(isElement());
        current_index = current_index->getNext();
}

/**void Deli::goToDeli() {
    if(((*control_obj).peek(*sync_obj)).getActionTime() == (*sync_obj).return_time()){
		insert(
**/
Customer_Obj Deli::current() {
        assert(isElement());
        return(current_index->getData());
}
void Deli::insert(Customer_Obj c) {
   node *currPtr;  // Single linked list -- need to keep track of the current
   node *prevPtr;  // and prevous nodes
   node *newPtr;   // This is the new node to be added to the list

   newPtr = new node(c);  // allocate space for the new node

   bool foundLoc;

   currPtr = head;
   prevPtr = NULL;
   foundLoc = false;
   while((currPtr != NULL) && (!foundLoc)) {  // search through the list
      if((currPtr->getData()).getFullName() > c.getFullName()){             // and find where the element should be added
                  foundLoc = true;                    // note the list is in increasing order
				  position++;
      }
          else {
                  prevPtr = currPtr;
                  currPtr = currPtr->getNext();
				  position++;
          }
   }


   if(!foundLoc) {
           // CASE 1: EMPTY LIST
           if(head == NULL) {
                   head = newPtr;
                   tail = newPtr;
           }
           // CASE 2: NEEDS TO GO AT THE END OF THE LIST
           else {
                   prevPtr->setNext(newPtr);
                   tail = newPtr;
       }
   }
   else {
           // CASE 3: NEEDS TO GO AT THE FRONT OF THE LIST
           if(currPtr == head) {
                   newPtr->setNext(head);
                   head = newPtr;
           }
           // CASE 4: GOES IN THE MIDDLE OF THE LIST
           else {
                   prevPtr->setNext(newPtr);
                   newPtr->setNext(currPtr);
           }
   }
    setTimeInLine(position);
	//used to keep track of the longest wait time
	if(getTimeInLine() > longestWait) {
		longestWait = getTimeInLine();
	}
	//used to calculate average wait time
	timeArray[++timeArrayCounter] = getTimeInLine();

}
Customer_Obj Deli::remove() {
   node *currPtr;
   node *delPtr;


   currPtr = head;
   delPtr = currPtr;
   // make sure head isn't pointing to garbage data
	if(head->getNext()!=NULL)
		head = head->getNext();
	else
		head=tail=NULL;
   delete delPtr;    		// deallocate the space
   return(delPtr->getData());
   //keep track of the number of deli customers served
   served++;
   
}

Customer_Obj Deli::peek() {
		// return the customer_obj from the front of the list
        Customer_Obj empty_customer;
        if(!isEmpty()) {
                      // cout << ((*head).getData()).getFirstName();
                return(head->getData());
        }
        else
            return(empty_customer);
}

void Deli::setStats() {
	numServed = served;
	//longestWait = lWait;
	int totalTime = 0;
	
	for(int i = 0;i<1000;i++) {
		totalTime += timeArray[i];
	}
	int avgTime = (int)totalTime/numServed;
	averageTime = avgTime;
}

int Deli::getAverageTime() {
	return(averageTime);
}

int Deli::getLongestWait() {
	return(longestWait);
}

int Deli::getNumServed() {
	return(numServed);
}
	
void Deli::show_stats() {
setStats();
Time avg = getAverageTime();
Time longest = getLongestWait();

cout<<"--Deli--"<<endl;
cout<< getNumServed() << " customers processed"<<endl;
cout<< "Longest wait time:  "; longest.dispTime(); cout << endl;
cout<< "Average wait time:  "; avg.dispTime(); cout << endl;

}
